home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / infoserv / gopher / Unix / GopherTools / gla.Z / gla
Encoding:
Text File  |  1993-09-23  |  9.7 KB  |  422 lines

  1. #!/usr/local/bin/perl
  2. # gla, boone, 06/18/92
  3. # Gopher log analyzer
  4. # Copyright (C) 1992, Michigan State University Board of Trustees
  5. #
  6. # Version 1.1
  7. #
  8. # Mail to: Dennis Boone <drbmaint@msu.edu>
  9. #
  10. # Modifications:
  11. # 06/18/92 Boone      Initial coding
  12. # 11/13/92 Boone      Added percentages
  13. # End Modifications
  14. #
  15. # Description:
  16. # gla reads a gopher log file and extracts statistics: times a file was
  17. # referenced and times any given domain came calling.  Host names and
  18. # IP addresses are relieved of the most specific portion to ensure privacy.
  19. # There are five sections in the gla report: Hostnames in alpha order, 
  20. # hostnames in order of frequency, filenames in alpha order, filenames in
  21. # order of frequency, and overall statistics.  Each section can be completely
  22. # eliminated with a command line option.  In addition, the number of hosts or
  23. # files reported can be limited using a command line option, for example to
  24. # generate a "most popular file" report.
  25. #
  26. # The gopher log is structured as follows:
  27. #
  28. #    date/time [port] hostname : action
  29. #
  30. #    date/time is a standard unix date format: ddd mmm dd hh:mm:ss yyyy
  31. #    port is the client port number; it isn't present in the log files
  32. #        written by all versions of the gopher server
  33. #    hostname is the fqdn or IP address of the calling host
  34. #    action is one of the following:
  35. #        retrieved file path
  36. #        retrieved directory path
  37. #        Root Connection
  38. #
  39. #       In addition, older versions of gopherd logged a start time in the
  40. #       log file, which is filtered.
  41. #
  42. #    Usage:  gla  [options]  <logfile  >reportfile
  43. #
  44. #    options:
  45. #      -ha       skip host-alpha section of report
  46. #      -hf       skip host-freq section of report
  47. #      -fa       skip file-alpha section of report
  48. #      -ff       skip file-freq section of report
  49. #      -sum      skip summary section of report
  50. #      -hlim n   limit host sections of report to n hosts
  51. #      -flim n   limit file sections of report to n files
  52. #
  53. # End Description
  54.  
  55. $home = $ENV{'HOME'};
  56. push(@INC, "$home/bin");
  57.  
  58. $mname{"Jan"} = 0; $mname{"Jul"} = 6;
  59. $mname{"Feb"} = 1; $mname{"Aug"} = 7;
  60. $mname{"Mar"} = 2; $mname{"Sep"} = 8;
  61. $mname{"Apr"} = 3; $mname{"Oct"} = 9;
  62. $mname{"May"} = 4; $mname{"Nov"} = 10;
  63. $mname{"Jun"} = 5; $mname{"Dec"} = 11;
  64.  
  65. $secs_leap = 31622400;
  66. $secs_norm = 31536000;
  67. $secs_day = 86400;
  68. $secs_hour = 3600;
  69. $d28 = 2419200;
  70. $d29 = 2505600;
  71. $d30 = 2592000;
  72. $d31 = 2678400;
  73. @secs_month = ($d31, $d28, $d31, $d30, $d31, $d30, 
  74.                $d31, $d31, $d30, $d31, $d30, $d31);
  75. @secs_leap_month = ($d31, $d29, $d31, $d30, $d31, $d30, 
  76.                     $d31, $d31, $d30, $d31, $d30, $d31);
  77.  
  78. #
  79. # Is it leap year?
  80. #
  81. sub isleap
  82. {
  83.     local($i) = @_;
  84.  
  85.     if ($i % 4) { return 0; }
  86.     if ((!($i % 100)) && ($i % 400)) { return 0; } else { return 1; }
  87. }
  88.  
  89. #
  90. # Compute seconds since Jan 1, 1970 without going south like timelocal()
  91. #
  92. sub epoch
  93. {
  94.     local($tstr) = @_;
  95.     local($i);
  96.  
  97.     @parts = unpack("a3 x a3 x a2 x a2 x a2 x a2 x a4", $tstr);
  98.     if (substr($parts[2], 0, 1) == " ") 
  99.         { $parts[2] = substr($parts[2], 1, 1); }
  100.     $since = 0;
  101.     for ($i = 1970; $i < $parts[6]; $i++)
  102.     {
  103.         if (&isleap($i))
  104.         {
  105.             $since += $secs_leap;
  106.         }
  107.         else
  108.         {
  109.             $since += $secs_norm;
  110.         }
  111.     }
  112.     for ($i = 0; $i < $mname{$parts[1]}; $i++)
  113.     {
  114.         if (&isleap($parts[6]))
  115.         {
  116.             $since += $secs_leap_month[$i];
  117.         }
  118.         else
  119.         {
  120.             $since += $secs_month[$i];
  121.         } 
  122.     }
  123.     for ($i = 1; $i < $parts[2]; $i++)
  124.     {
  125.         $since += $secs_day;
  126.     }
  127.     for ($i = 0; $i < $parts[3]; $i++)
  128.     {
  129.         $since += $secs_hour;
  130.     }
  131.     for ($i = 0; $i < $parts[4]; $i++)
  132.     {
  133.         $since += 60;
  134.     }
  135.     $since += $parts[5];
  136.     return $since;
  137. }
  138.  
  139. #
  140. # Comparison routines for sorting on the value of an entry in an 
  141. # associative array
  142. #
  143. sub hostbyval                # Sort on count of calls from this host
  144. {
  145.     $host{$b} <=> $host{$a};
  146. }
  147.  
  148. sub filebyval                # Sort on count of calls for this file
  149. {
  150.     $file{$b} <=> $file{$a};
  151. }
  152.  
  153. #
  154. # Clip name, leaving domain
  155. # Or keep first three octets of IP address
  156. #
  157. sub chophost
  158. {
  159.     local($h) = @_;
  160.     local($r);
  161.     $h =~ tr/[A-Z]/[a-z]/;        # Force lowercase
  162.     if (/([0-9]*\.){3}[0-9]*/)    # Is it an IP address?
  163.     {
  164.         $h =~ /([0-9]+\.[0-9]+\.[0-9]+\.)[0-9]+/;
  165.         $r = $1;
  166.     }
  167.     else
  168.     {
  169.         $h =~ /[^\s.]+\.([^\s]+)/;
  170.         $r = $1;
  171.     }
  172.     return $r;
  173. }
  174.  
  175. #
  176. # Increment appropriate counters
  177. #
  178. sub tally
  179. {
  180.     / ([^\s]+) :/;            # Extract host name from log line
  181.     $th = &chophost($1);        # Remove incriminating information
  182.     $tf = $2 if /retrieved ([^\s]+) (.*)$/;
  183.     $tf = "Root Connection" if /Root Connection/;
  184.     $host{$th}++;
  185.     $file{$tf}++;
  186.     $callcnt++;
  187.     if (! ($callcnt % 500))
  188.     {
  189.         print STDERR "$callcnt records processed.\r";
  190.     }
  191.     if ($firstline)
  192.     {
  193.         $firstline = 0;
  194.         $firstdate = substr($_, $[, 24);
  195.     }
  196.     $lastdate = substr($_, $[, 24);
  197. }
  198.  
  199. #
  200. # Print reports
  201. #
  202. sub report
  203. {
  204.     foreach (keys %file)
  205.     {
  206.         $filecnt++;
  207.     }
  208.     foreach (keys %host)
  209.     {
  210.         $hostcnt++;
  211.     }
  212.  
  213.     if ($haflag)
  214.     {
  215.         # Report domain names in alpha order
  216.         $^ = "TOPHOSTALPHA";        # Set top-of-form format
  217.         $~ = "HOSTALPHA";        # Set detail format
  218.         local($i) = 0;
  219.         foreach $key (sort keys(%host))
  220.         {
  221.             $host = $key;
  222.             $calls = $host{$key};
  223.             $pct = sprintf("%5.1f", ($calls / $callcnt) * 100);
  224.             write;
  225.             $i++; last if ($hlim && ($i == $hlim));
  226.         }
  227.         $- = 0;                # Force end-of-page
  228.     }
  229.  
  230.     if ($hfflag)
  231.     {
  232.         # Report domain names in descending order of call frequency
  233.         $^ = "TOPHOSTFREQ";
  234.         $~ = "HOSTFREQ";
  235.         local($i) = 0;
  236.         local($tcalls) = 0;
  237.         foreach $key (sort hostbyval keys(%host))
  238.         {
  239.             $host = $key;
  240.             $calls = $host{$key};
  241.             $tcalls += $calls;
  242.             $pct = sprintf("%5.1f", ($calls / $callcnt) * 100);
  243.             $cum = sprintf("%5.1f", ($tcalls / $callcnt) * 100);
  244.             write;
  245.             $i++; last if ($hlim && ($i == $hlim));
  246.         }
  247.         $- = 0;
  248.     }
  249.  
  250.     if ($faflag)
  251.     {
  252.         # Report file names in alpha order
  253.         $^ = "TOPFILEALPHA";
  254.         $~ = "FILEALPHA";
  255.         local($i) = 0;
  256.         foreach $key (sort keys(%file))
  257.         {
  258.             $file = $key;
  259.             $calls = $file{$key};
  260.             $pct = sprintf("%5.1f", ($calls / $callcnt) * 100);
  261.             write;
  262.             $i++; last if ($flim && ($i == $flim));
  263.         }
  264.         $- = 0;
  265.     }
  266.  
  267.     if ($ffflag)
  268.     {
  269.         # Report file names in descending order of frequency of use
  270.         $^ = "TOPFILEFREQ";
  271.         $~ = "FILEFREQ";
  272.         local($i) = 0;
  273.         local($tcalls) = 0;
  274.         foreach $key (sort filebyval keys(%file))
  275.         {
  276.             $file = $key;
  277.             $calls = $file{$key};
  278.             $tcalls += $calls;
  279.             $pct = sprintf("%5.1f", ($calls / $callcnt) * 100);
  280.             $cum = sprintf("%5.1f", ($tcalls / $callcnt) * 100);
  281.             write;
  282.             $i++; last if ($flim && ($i == $flim));
  283.         }
  284.         $- = 0;
  285.     }
  286.  
  287.     if ($sumflag)
  288.     {
  289.         # Report cheesy counters
  290.         $^ = "TOPSUMMARY";
  291.         $~ = "SUMMARY";
  292.         write;
  293.     }
  294. }
  295.  
  296. ###############################################################################
  297.  
  298. $= = 55;                # Max lines per page
  299. $[ = 0;                    # Array subscript base
  300. $firstline = 1;                # Keep first date stamp in file
  301. $haflag = 1;                # Want host-alpha report?
  302. $hfflag = 1;                # Want host-freq report?
  303. $faflag = 1;                # Want file-alpha report?
  304. $ffflag = 1;                # Want file-freq report?
  305. $sumflag = 1;                # Want summary report?
  306. $hlim = 0;                # Unlimited number of hosts in report
  307. $flim = 0;                # Unlimited number of files in report
  308.  
  309. while ($arg = shift @ARGV)
  310. {
  311.     if ($arg eq "-ha") { $haflag = 0; next; }
  312.     if ($arg eq "-hf") { $hfflag = 0; next; }
  313.     if ($arg eq "-fa") { $faflag = 0; next; }
  314.     if ($arg eq "-ff") { $ffflag = 0; next; }
  315.     if ($arg eq "-sum") { $sumflag = 0; next; }
  316.     if ($arg eq "-hlim") { $hlim = shift @ARGV; next; }
  317.     if ($arg eq "-flim") { $flim = shift @ARGV; next; }
  318.     print STDERR "$ARGV[0]: unrecognized argument: $arg\n";
  319.     exit(1);
  320. }
  321.  
  322. while (<>)                # Gobble the whole log file
  323. {
  324.     next if /^$/;            # Throw away blank lines
  325.     next if /Starting gopher daemon/;    # Throw away start lines
  326.     &tally;                # Keep count
  327. }
  328. print STDERR "$callcnt records processed.\n";
  329. $startjul = &epoch($firstdate);
  330. $endjul = &epoch($lastdate);
  331. $period = $endjul - $startjul;
  332. $callspace = $period / $callcnt;
  333. &report;                # Print reports
  334. exit;
  335.  
  336. ###############################################################################
  337.  
  338.     format TOPHOSTALPHA =
  339.  
  340. Michigan State University Gopher Log Analyzer                      Page: @<<
  341. $%
  342. Client Domains by Name
  343.  
  344. Domain Domain or IP Address                              Calls      %
  345. -----------------------------------------------------  -------  -----
  346. .
  347.  
  348.     format HOSTALPHA =
  349. @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  @>>>>>>  @>>>>
  350. $host $calls $pct
  351. .
  352.  
  353.     format TOPHOSTFREQ =
  354.  
  355. Michigan State University Gopher Log Analyzer                      Page: @<<
  356. $%
  357. Client Domains by Frequency of Use
  358.  
  359. Host Domain or IP Address                                Calls      %    Cum
  360. -----------------------------------------------------  -------  -----  -----
  361. .
  362.  
  363.     format HOSTFREQ =
  364. @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  @>>>>>>  @>>>>  @>>>>
  365. $host $calls $pct $cum
  366. .
  367.  
  368.     format TOPFILEALPHA =
  369.  
  370. Michigan State University Gopher Log Analyzer                      Page: @<<
  371. $%
  372. Retrieved Items by Name
  373.  
  374. File Description                                          Uses      %
  375. -----------------------------------------------------  -------  -----
  376. .
  377.  
  378.     format FILEALPHA =
  379. @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  @>>>>>>  @>>>>
  380. $file $calls $pct
  381. .
  382.  
  383.     format TOPFILEFREQ =
  384.  
  385. Michigan State University Gopher Log Analyzer                      Page: @<<
  386. $%
  387. Retrieved Items by Frequency of Use
  388.  
  389. File Description                                          Uses      %    Cum
  390. -----------------------------------------------------  -------  -----  -----
  391. .
  392.  
  393.     format FILEFREQ =
  394. @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  @>>>>>>  @>>>>  @>>>>
  395. $file $calls $pct $cum
  396. .
  397.  
  398.     format TOPSUMMARY =
  399.  
  400. Michigan State University Gopher Log Analyzer                      Page: @<<
  401. $%
  402. Report Summary
  403.  
  404. .
  405.  
  406.     format SUMMARY =
  407.                   Starting date: @<<<<<<<<<<<<<<<<<<<<<<<<
  408. $firstdate
  409.                     Ending date: @<<<<<<<<<<<<<<<<<<<<<<<<
  410. $lastdate
  411.  
  412.                     Total calls: @<<<<<<<<<
  413. $callcnt
  414.   Average seconds between calls: @<<<<<<
  415. $callspace
  416.  
  417.               Different domains: @<<<<<<<<<
  418. $hostcnt
  419.                 Different files: @<<<<<<<<<
  420. $filecnt
  421. .
  422.